﻿using Microsoft.Extensions.Caching.Distributed;
using Newtonsoft.Json;
using System.Text;

namespace Infrastructure.Cache
{
    /// <summary>
    /// 分布式缓存
    /// </summary>
    public class DistributedCacheManager
    {
        protected IDistributedCache cache;  // 声明一个保护类型的分布式缓存接口变量

        // 构造函数，接收一个IDistributedCache接口的实例作为参数
        public DistributedCacheManager(IDistributedCache cache)
        {
            this.cache = cache;  // 初始化类中的分布式缓存接口变量
        }

        // 设置缓存项
        public void Set(string key, object value, DistributedCacheEntryOptions distributedCacheEntryOptions)
        {
            // 将对象序列化为 JSON 字符串，忽略循环引用并包含类型信息
            string s = JsonConvert.SerializeObject(value, new JsonSerializerSettings
            {
                ReferenceLoopHandling = ReferenceLoopHandling.Ignore,
                TypeNameHandling = TypeNameHandling.All
            });
            byte[] bytes = Encoding.UTF8.GetBytes(s);  // 将 JSON 字符串转换为 UTF-8 字节数组
            cache.Set(key, bytes, distributedCacheEntryOptions);  // 将字节数组存入缓存中，使用给定的选项
            Refresh(key);  // 刷新缓存中指定键的缓存项
        }

        // 检查指定键的缓存项是否存在
        public bool Exist(string key)
        {
            byte[] array = cache.Get(key);  // 从缓存中获取指定键的字节数组
            return (array != null);  // 如果字节数组不为空，返回 true，表示缓存项存在；否则返回 false
        }

        // 获取指定键的缓存项，并返回解析后的泛型类型 T
        public T Get<T>(string key, out bool isExisted)
        {
            byte[] array = cache.Get(key);  // 从缓存中获取指定键的字节数组
            if (array == null)
            {
                isExisted = false;  // 如果字节数组为空，设置 isExisted 为 false
                return default(T);  // 返回 T 类型的默认值（通常为 null），表示未找到缓存项
            }

            string jsonString = Encoding.UTF8.GetString(array);  // 将字节数组转换为 UTF-8 编码的 JSON 字符串
            isExisted = true;  // 设置 isExisted 为 true，表示找到了缓存项
            return JsonConvert.DeserializeObject<T>(jsonString, new JsonSerializerSettings
            {
                TypeNameHandling = TypeNameHandling.All  // 反序列化时包含类型信息
            });
        }

        // 移除指定键的缓存项
        public void Remove(string key)
        {
            cache.Remove(key);  // 从缓存中移除指定键的缓存项
        }

        // 刷新指定键的缓存项
        public void Refresh(string key)
        {
            cache.Refresh(key);  // 刷新缓存中指定键的缓存项
        }
    }
}
